#include <algorithm>
#include "TournamentSelection.h"
#include "../../Random/MyRandom.h"
#include "../../Util/SolutionPtrComparator.h"

TournamentSelection::TournamentSelection()
{
    tournamentSize = 2;
}

TournamentSelection::TournamentSelection(unsigned int newTournamentSize)
{
    setTournamentSize(newTournamentSize);
}

void TournamentSelection::setTournamentSize(unsigned int newSize)
{
    if (newSize < 2) {
        newSize = 2;
    }
    
    tournamentSize = newSize;
}

void TournamentSelection::select(Solution* &child1, Solution* &child2)
{
    unsigned int genePoolSize = genePool.size();
    tournamentContainer.clear();
    
    //add N contenders to our tournament
    for (unsigned int i = 0; i < tournamentSize; ++i) {
        unsigned int pos = MyRandom::randInt(0, genePoolSize - 1);
        tournamentContainer.push_back(genePool[pos]);
    } 
        
    //sort the contenders into decending order
    sort(genePool.begin(), genePool.end(), SolutionPtrGTComparator());
    
    //then pick the best one
    child1 = tournamentContainer[0];
    
    //repeat for child2:
    tournamentContainer.clear();
    
    for (unsigned int i = 0; i < tournamentSize; ++i) {
        unsigned int pos = MyRandom::randInt(0, genePoolSize - 1);
        tournamentContainer.push_back(genePool[pos]);
    }
    
    sort(genePool.begin(), genePool.end(), SolutionPtrGTComparator());
    
    child2 = tournamentContainer[0];
}

void TournamentSelection::clean() {
    genePool.clear();
    tournamentContainer.clear();
}

void TournamentSelection::prepare(vector<Solution*> newPool)
{
    clean();
    genePool = newPool;
}

Selection* TournamentSelection::getSelection() {
    return new TournamentSelection();
}

Selection* TournamentSelection::getSelection(unsigned int tournamentSize) {
    return new TournamentSelection(tournamentSize);
}
